Node.js async/await - NODEJS教程

Node.js async/await

在 Node.js 中, async/await 是一种处理异步操作的语法糖。

async/await 基于 Promise,但让异步代码看起来更像同步代码,极大地提高了代码的可读性和可维护性。

async 关键字用于声明一个函数是异步的,而 await 关键字用于等待一个 Promise 的解决(resolve)或拒绝(reject)。

使用 async/await 可以避免回调地狱(callback hell)并使错误处理更加直观。

JavaScript 是单线程的,遇到异步任务(如 setTimeout 或网络请求)时,会交给 浏览器 API 处理,完成后将回调放入消息队列。

事件循环不断检查调用栈是否为空,如果是,就从队列中取出回调推入调用栈执行。这样既不会阻塞主线程,又能按顺序处理异步结果。


基本语法

async 函数

任何函数都可以通过添加 async 关键字变成异步函数:

示例代码
asyncfunctionmyFunction(){return"Hello World";}

async 函数总是返回一个 Promise。如果返回值不是 Promise,它会被自动包装成 Promise。

await 表达式

await 只能在 async 函数内部使用,它会暂停函数的执行,等待 Promise 解决,然后继续执行并返回结果:

示例代码
asyncfunctionfetchData(){constresponse=await fetch('https://api.example.com/data');constdata=await response.json();returndata;}

错误处理

try/catch 方式

处理 async/await 错误最常用的方法是使用 try/catch

示例代码
asyncfunctiongetUser(){try{constresponse=await fetch('https://api.example.com/user');constuser=await response.json();returnuser;}catch(error){console.error('Error fetching user:',error);throwerror;// 可以选择重新抛出错误}}

直接处理 Promise

你也可以直接处理返回的 Promise:

示例代码
getUser().then(user=>console.log(user)).catch(error=>console.error(error));

实际应用示例

并行执行多个异步操作

使用 Promise.all 结合 async/await 可以并行执行多个异步操作:

示例代码
asyncfunctionfetchMultipleUrls(urls){try{constrequests=urls.map(url=>fetch(url));constresponses=await Promise.all(requests);constdata=await Promise.all(responses.map(r=>r.json()));returndata;}catch(error){console.error('Error fetching data:',error);throwerror;}}

数据库操作示例

示例代码
asyncfunctiongetUserAndPosts(userId){try{constuser=await User.findById(userId);constposts=await Post.find({userId});return{user,posts};}catch(error){console.error('Database error:',error);throwerror;}}

最佳实践

  1. 总是处理错误 :不要忽略 await 可能抛出的错误,使用 try/catch .catch() 处理
  2. 避免不必要的 await :如果不需要等待结果,可以直接返回 Promise
  3. 合理使用并行 :多个独立的异步操作应该并行执行(使用 Promise.all
  4. 保持代码清晰 :避免过深的 async/await 嵌套,必要时提取函数
  5. 注意性能影响 :每个 await 都会暂停函数执行,在循环中要特别注意

常见问题

async/await 与 Promise 的关系

async/await 是建立在 Promise 之上的语法糖。任何 async 函数都返回 Promise,任何 await 后面都可以接 Promise。

为什么我的 async 函数返回 undefined?

这可能是因为忘记在 await 前使用 return ,或者在 Promise 解决前函数就退出了。

可以在顶层使用 await 吗?

在 ES 模块中(文件以 .mjs 结尾或 package.json "type": "module" ),可以直接在顶层使用 await 。在 CommonJS 模块中,需要包裹在 async 函数中。

示例代码
// 在 ES 模块中constdata=await fetchData();console.log(data);